package cn.iocoder.yudao.module.trade.service.orderverifycode;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.trade.controller.admin.orderverifycode.vo.OrderVerifyCodePageReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.orderverifycode.vo.OrderVerifyCodeSaveReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.orderverifycode.OrderVerifyCodeDO;
import cn.iocoder.yudao.module.trade.dal.mysql.orderverifycode.OrderVerifyCodeMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_VERIFY_CODE_NOT_EXISTS;

/**
 * 订单核销码 Service 实现类
 *
 * @author 万民匠心
 */
@Service
@Slf4j
@Validated
public class OrderVerifyCodeServiceImpl implements OrderVerifyCodeService {

    public static final Long SART_NUMBER = 1000L;

    @Resource
    private OrderVerifyCodeMapper orderVerifyCodeMapper;
    @Resource
    private RedissonClient redissonClient;


    @Override
    public Long createOrderVerifyCode(OrderVerifyCodeSaveReqVO createReqVO) {
        // 自提code 1000 开始；店内用餐code 5000开始 ，首先查询
        createReqVO.setDate(LocalDate.now());
        //分布式锁，确保券码唯一
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String dateStr = createReqVO.getDate().format(formatter);
        //分布式锁key:店铺id + 日期
        String lockKey = createReqVO.getStoreId() + dateStr;
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试获取锁，等待10秒，锁自动释放时间为30秒
            boolean isLocked = lock.tryLock(3L, 30L, TimeUnit.SECONDS);
            if (isLocked) {
                // 执行逻辑
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("store_id", createReqVO.getStoreId());
                queryWrapper.eq("date", createReqVO.getDate());
                Long count = orderVerifyCodeMapper.selectCount(queryWrapper);
                Long code = SART_NUMBER + count + 1;
                //先查询当前最大的id
                OrderVerifyCodeDO orderVerifyCode = BeanUtils.toBean(createReqVO, OrderVerifyCodeDO.class);
                orderVerifyCode.setCode(code);
                orderVerifyCodeMapper.insert(orderVerifyCode);
                return orderVerifyCode.getCode();
            }else{
                // 未获得锁，处理锁定失败的情况
                log.error("获取生成取餐号redisson锁失败");
            }
        } catch (InterruptedException e) {
            log.error("获取生成取餐号redisson锁失败,error:{}" + e);
        } finally {
            // 解锁前检查当前线程是否持有该锁
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return null;

        // 返回

    }

    @Override
    public void updateOrderVerifyCode(OrderVerifyCodeSaveReqVO updateReqVO) {
        // 校验存在
        validateOrderVerifyCodeExists(updateReqVO.getId());
        // 更新
        OrderVerifyCodeDO updateObj = BeanUtils.toBean(updateReqVO, OrderVerifyCodeDO.class);
        orderVerifyCodeMapper.updateById(updateObj);
    }

    @Override
    public void deleteOrderVerifyCode(Long id) {
        // 校验存在
        validateOrderVerifyCodeExists(id);
        // 删除
        orderVerifyCodeMapper.deleteById(id);
    }

    private void validateOrderVerifyCodeExists(Long id) {
        if (orderVerifyCodeMapper.selectById(id) == null) {
            throw exception(ORDER_VERIFY_CODE_NOT_EXISTS);
        }
    }

    @Override
    public OrderVerifyCodeDO getOrderVerifyCode(Long id) {
        return orderVerifyCodeMapper.selectById(id);
    }

    @Override
    public PageResult<OrderVerifyCodeDO> getOrderVerifyCodePage(OrderVerifyCodePageReqVO pageReqVO) {
        return orderVerifyCodeMapper.selectPage(pageReqVO);
    }

}